
#include "utils.h"

#include "config.h"

#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/socket.h>

#include <cstdio>
#include <cstring>



using namespace std;


extern bool debugMode;


int readLine( int fd, string & line )
{
    line = "";

    // Read characters from the socket one by one.
    while ( true )
    {
        char c;
        int bytesRead = read( fd, &c, 1 );

        if ( bytesRead <= 0 )
            return bytesRead;

        if ( c == '\n')
            return line.size() + 1;

        // We ignore carriage returns, because they're a pain in the ass.
        if ( c != '\r' )
            line += c;
    }
}

int master_socket (int port){
    // Create the master socket.
    int masterSocket = socket( PF_INET, SOCK_STREAM, 0 );
    if ( masterSocket < 0 )
        return -1;

    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = htonl( INADDR_ANY );
    sin.sin_port = htons(port);

    int reuse = 1;
    setsockopt(masterSocket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));

    // Bind the socket and prepare if for incoming connection requests.
    if ( bind( masterSocket, (struct sockaddr *)( &sin ), sizeof( sin ) ) < 0 )
    {
        close( masterSocket );
        return -1;
    }
    if ( listen( masterSocket, 16 ) < 0 )
    {
        close( masterSocket );
        return -1;
    }

    /* Master socket is set as non-blockable so no deadlock regarding the mutex can occur. */
    int flags = fcntl(masterSocket, F_GETFL, 0);
    if (flags == -1 || (fcntl(masterSocket, F_SETFL, flags | O_NONBLOCK) == -1))
        return -1;

   return masterSocket;
}

void log(int level, const char * message)
{
    if ( level <= LOG_DEBUG && !debugMode )
        return;

    if ( !debugMode && Config::self()->useSyslog() )
    {
        syslog( level, message );
    }
    else
    {
        printf( message );
    }
}

void log( int level, const char * message, int intArg )
{
    if ( level <= LOG_DEBUG && !debugMode )
        return;

    if ( !debugMode && Config::self()->useSyslog() )
    {
        syslog( level, message, intArg );
    }
    else
    {
        printf( message, intArg );
    }
}

void log( int level, const char * message, const char * charArg )
{
    if ( level <= LOG_DEBUG && !debugMode )
        return;

    if ( !debugMode && Config::self()->useSyslog() )
    {
        syslog( level, message, charArg );
    }
    else
    {
        printf( message, charArg );
    }
}

void logError( int level, const char * message )
{
    if ( level <= LOG_DEBUG && !debugMode )
        return;

    if ( !debugMode && Config::self()->useSyslog() )
    {
        string s = message + string(": ") + strerror( errno ) + "\n";
        syslog( level, s.c_str() );
    }
    else
    {
        perror( message );
    }
}
